IterationEnvironment#

class IterationEnvironment(qs, iteration_amount, precompile=False)[source]#

This QuantumEnvironment can be used for reducing bottlenecks in compilation time. Many algorithms such as Grover or QPE require repeated execution of the same quantum circuit. When scaling up complex algorithms that perform a lot of non-trivial logic many iterations can significantly slow down the compilation speed. The IterationEnvironment remedies this flaw by recording the circuit of a single iteration and then duplicating the instructions the required amount of times.

Another bottleneck that can appear is the compile method as the qubit allocation algorithm can also scale bad for really large algorithms. For this problem the IterationEnvironment exposes the precompile keyword. Setting this keyword to True will perform the Qubit allocation algorithm on the QuantumEnvironments content and then (if necessary) allocate another QuantumVariable to accomodate the workspace qubits of the compilation result. This way there is only a single (de)allocation per IterationEnvironment.

Note

Code that is executed within a IterationEnvironment may not delete previously created QuantumVariable and every created QuantumVariable inside this Quantum Environments has to be deleted before exit.

Parameters:
qsQuantumSession

The QuantumSession in which the iterated code should be performed. QuantumVariables that have been created outside this QuantumEnvironment need to be registered in this QuantumSession.

iteration_amountinteger

The amount of iterations to perform.

precompilebool

If set to True, the qubit allocation algorithm will be run, once this QuantumEnvironment is compiled. This can significantly reduce the workload for a later compile call as there is only a single allocation per IterationEnvironment to handle. The default is False.

Examples

We perform a simple addition circuit multiple times:

from qrisp import QuantumFloat, IterationEnvironment

a = QuantumFloat(5)

with IterationEnvironment(a.qs, iteration_amount = 10):

    a += 1

Evaluate the result

>>> print(a)
{10: 1.0}

Precompilation

Squaring a QuantumFloat uses the qrisp.sbp_mult() function, which has a high demand of ancilla qubits. Therefore many iterations can quickly overload the allocation algorithm.

def benchmark_function(use_iter_env = False):
    qf = QuantumFloat(5)

    if use_iter_env:

        with IterationEnvironment(qf.qs, 20, precompile = True):

            temp = qf*qf
            temp.uncompute()
    else:

        for i in range(20):

            temp = qf*qf
            temp.uncompute()

    compiled_qc = qf.qs.compile()

Benchmark results:

import time

start_time = time.time()
benchmark_function(False)
print("Time taken without IterationEnvironment: ", time.time() - start_time)
#Takes 55s

start_time = time.time()
benchmark_function(True)
print("Time taken with IterationEnvironment: ", time.time() - start_time)
#Takes 6s